package com.htd.erp.product;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import javax.enterprise.context.ConversationScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Instance;
import javax.faces.convert.Converter;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.htd.erp.common.DataRepository;
import com.htd.erp.common.Repository;
import com.htd.erp.exception.CascadeDeleteException;
import com.htd.erp.model.Classification;
import com.htd.erp.web.AbstractEntityConverter;

/**
 * @author Zhang Guilin
 *
 */
@Named
@ConversationScoped
public class ClassificationConverter extends AbstractEntityConverter<Classification> implements Converter, Serializable {
	
	private static final long serialVersionUID = 5310095134693273140L;
	
	private static final Logger logger = LoggerFactory.getLogger(ClassificationConverter.class);
	
	@DataRepository
	@Inject
	private EntityManager entityManager;
	
	@Inject
	private Instance<Repository> genericRepository;
	
	private Classification selectedNode;
	
	public void addSubClassification() {
		selectedNode = new Classification(selectedNode);
	}
	
	public void save() {
		selectedNode = selectedNode.isNew()? getRepository().create(selectedNode) : getRepository().update(selectedNode);
		logger.info("Classification (id:{}) is saved.", selectedNode.getId());
	}
	
	public void delete()  {
		if(hasNoSubClassifications() && hasNoAssociatedProducts()) {
			genericRepository.get().delete(Classification.class, selectedNode.getId());
			selectedNode = null;
			return;
		}
		
		throw new CascadeDeleteException("Can not delete this classification, sub classifications exist or products associate with it.");
	}
	
	private boolean hasNoAssociatedProducts() {
		return selectedNode.getProducts().isEmpty();
	}

	private boolean hasNoSubClassifications() {
		return selectedNode.getSubClassifications().isEmpty();
	}

	public void observeClassificationCreated(@Observes ClassificationCreatedEvent event) {
		list = buildSamples();
	}
	
	@Override
	protected Classification find(String id, Collection<Classification> collection) {
		for(Classification s : collection) {
			if(StringUtils.equals(s.getId().toString(),id)) {
				return s;
			}
			if(!s.getSubClassifications().isEmpty()) {
				Classification target = find(id, s.getSubClassifications());
				if(target != null) {
					return target;
				}
			}
		}
		return null;
	}
	
	@Override
	@SuppressWarnings("unchecked")
	protected List<Classification> buildSamples() {
		Query query = entityManager.createQuery("FROM Classification WHERE parentClassification is null AND deleted = false");
		return query.getResultList();
	}
	
	@Override
	protected Class<Classification> getEntityClass() {
		return Classification.class;
	}

	public Classification getSelectedNode() {
		return selectedNode;
	}

	public void setSelectedNode(Classification selectedNode) {
		this.selectedNode = selectedNode;
	}
}
